#include "threadPool.h"
char base_addr[200]="/home/lh/project1";


int threadPoolInit(threadPool_t *pthreadPool,int workerNum){
    tidArrInit(&pthreadPool->tidArr, workerNum);
    taskQueueInit(&pthreadPool->taskQueue);
    pthread_mutex_init(&pthreadPool->mutex, NULL);
    pthread_cond_init(&pthreadPool->cond, NULL);
    pthreadPool->exitFlag = 0;
    return 0;
}


int recvCommandPacket(int netfd,int *cmd,int *length,char *addr)
{
    int j=0;
    recv(netfd,cmd,sizeof(int),MSG_WAITALL);
    recv(netfd,length,sizeof(int),MSG_WAITALL);
    if(*length==0)
    {
        *length=1;
        j=1;
    }
    recv(netfd,addr,*length,MSG_WAITALL);
    if(j==1)
    {
        *length=0;
    }

    return 0;
}



static int stackPush(char **now_addr,char *dir_name,int *size){
    now_addr[*size]=dir_name;
    (*size)++;
    return 0;
}
static int stackPop(char**now_addr,int *size){
    if((*size)==0){
        printf("in the root dir\n");
        return 1;
    }
    (*size)--;
    char *p=now_addr[*size];
    free(p);
    now_addr[*size]=NULL;
    return 0;
}
int compare(const void*a,const void*b){
    return strcmp(*(const char**)a,*(const char**)b);
}
int cdFunc(char*path,int path_size,char *now_addr){
    if(path_size==0){
        memcpy(now_addr,".",1);
        return 0;
    }
    char*tmp=(char*)calloc(strlen(now_addr),sizeof(char));
    memcpy(tmp,now_addr,strlen(now_addr));
    char**spath=(char**)calloc(path_size,sizeof(char*));
    for(int i=0;i<path_size;i++){
        char*buf=(char*)calloc(1024,sizeof(char));
        spath[i]=buf;
    }
    char**now_spath=(char**)calloc(path_size+strlen(now_addr),sizeof(char*));
    for(int i=0;i<path_size+strlen(now_addr);i++){
        char*buf=(char*)calloc(1024,sizeof(char));
        now_spath[i]=buf;
    }
    int pathsize;
    pathSeparation(path,spath,&pathsize);
    int now_addr_size;
    pathSeparation(now_addr,now_spath,&now_addr_size);
    for(int i=0;i<pathsize;i++){
        if(strcmp(spath[i],"..")==0){
            free(spath[i]);
            stackPop(now_spath,&now_addr_size);
        }
        else if(strcmp(spath[i],".")==0){
            free(spath[i]);
            continue;
        }
        else{
            stackPush(now_spath,spath[i],&now_addr_size);
        }
    }
    bzero(now_addr,strlen(now_addr));
    if(now_addr_size==0){
        memcpy(now_addr,".",1);
        return 0;
    }
    strcat(now_addr,now_spath[0]);
    for(int i=1;i<now_addr_size;i++){
        strcat(now_addr,"/");
        strncat(now_addr,now_spath[i],strlen(now_spath[i]));
    }
    printf("now_addr=%s\n",now_addr);
    int res=access(now_addr,F_OK);
    if(res==-1){
        printf("Can not find this file\n");
        memcpy(now_addr,tmp,strlen(tmp));
        free(tmp);
        return -1;
    }
    free(spath);
    for(int i=0;i<now_addr_size;i++){
        free(now_spath[i]);
    }
    free(tmp);
    free(now_spath);
    return 0;
}
int lsFunc(char *now_addr,char* path,int path_size,char* buf){
    cdFunc(path,path_size,now_addr);
    DIR *dir=opendir(now_addr);
    if(dir==NULL){
        printf("opendir fail\n");
        return -1;
    }
    struct dirent *entry;
    char *manu[1024]={0};
    int pmanu=0;
    while((entry=readdir(dir))!=NULL){
        if(strcmp(entry->d_name,".")==0||strcmp(entry->d_name,"..")==0){
            continue;
        }
        manu[pmanu]=entry->d_name;
        pmanu++;
    }
    qsort(manu,pmanu,sizeof(char*),compare);
    for(int i=0;i<pmanu;i++){
        strncat(buf,manu[i],strlen(manu[i]));
        strcat(buf,"\n");
    }
    closedir(dir);
    return 0;
}
int pathSeparation(char*path,char**spath,int *size){
    if(spath==NULL){
        printf("spatch no space\n");
        //exit(1);
        return -1;
    }
    *size=0;
    char *p=path;
    char**q=spath;
    while(*p==' '){
        p++;
    }
    while(p!=NULL&&*p!=0){
        if(*p=='/'){
            p++;
        }
        else{
            while(*p==' '){
                p++;
            }
            int i=0;
            while(p!=NULL&&*p!=0&&*p!='/'){
                (*q)[i]=*p;
                i++;
                p++;
            }
            q++;
            (*size)++;
        }
    }
    return 0;
}
int pwdFunc(const char*addr,char *buf)
{
    strcpy(buf,addr);
    printf("%s\n",buf);
    return 0;
}
int mkdirFunc(const char*addr,const char*dirname)
{
    //传来的地址是/usr1/....所以先分割字符串，把usr1去掉
    //也可能传来 . ..,但是不用考虑


    char temp[200]={0};
    strcpy(temp,addr);
    char **segments=NULL;
    int count=split_str(temp,&segments);
    bzero(temp,sizeof(temp));
    for(int i=1;i<count;i++)
    {
        strcat(temp,"/");
        strcat(temp,segments[i]);
    }
    printf("temp=%s\n",temp);

    char dir_real_addr[200]={0};
    strcpy(dir_real_addr,base_addr);
    char tempbuf[100]={0};
    tempbuf[0]='/';
    strcat(tempbuf,dir_real_addr);
    strcat(dir_real_addr,temp);//得到真实目录；
    strcat(dir_real_addr,"/");
    strcat(dir_real_addr,dirname);//得到该目录的完整地址
    printf("dir_real_addr=%s\n",dir_real_addr);
    /* strcpy(dir_real_addr,cur_real_addr); */
    int ret=access(dir_real_addr,F_OK);//判断该目录是否已经存在
    if(ret==0)//存在，继续判断是文件还是目录
    {
        DIR* dirp=opendir(dir_real_addr);//判断是目录还是文件
        if(dirp!=NULL)//是相同的目录，不能创建
        {
            printf("exit same dir,cannot mkdir again!\n");
            return -1;
        }
    }
    //走到这说明该目录不存在
    mode_t mode;
    sscanf("777","%o",&mode);
    ret=mkdir(dir_real_addr,mode);
    ERROR_CHECK(ret,-1,"mkdir");
    printf("mkdir success!\n");

    for(int i=0;i<count;i++)
    {
        free(segments[i]);
    }
    free(segments);

    return 0;
}
int rmdirFunc(const char*addr,const char*dirname)
{
    //传来的地址是/usr1/....所以先分割字符串，把usr1去掉
    //也可能传来 . ..,但是不用考虑

    char temp[100]={0};
    strcpy(temp,addr);
    char **segments=NULL;
    int count=split_str(temp,&segments);
    bzero(temp,sizeof(temp));
    for(int i=1;i<count;i++)
    {
        strcat(temp,"/");
        strcat(temp,segments[i]);
    }

    char dir_real_addr[200]={0};
    strcpy(dir_real_addr,base_addr);
    strcat(dir_real_addr,temp);//得到真实目录；
    strcat(dir_real_addr,"/");
    strcat(dir_real_addr,dirname);//得到该目录的完整地址
    printf("dir_real_addr=%s\n",dir_real_addr);
    /* strcpy(dir_real_addr,cur_real_addr); */
    int ret=access(dir_real_addr,F_OK);//判断该文件或目录是否存在于当前目录
    ERROR_CHECK(ret,-1,"access");

    DIR* dirp=opendir(dir_real_addr);//判断是目录还是文件
    if(dirp==NULL)
    {
        printf("addr is not exit\n");
        exit(-1);
    }
    //走到这说明该目录存在
    ret=rmdir(dir_real_addr);
    ERROR_CHECK(ret,-1,"rmdir");
    printf("rmdir success!\n");

    for(int i=0;i<count;i++)
    {
        free(segments[i]);
    }
    free(segments);
    return 0;
}
int split_str(const char* addr, char ***segment) {
    // 1. 复制原始字符串（strtok会修改源字符串）
    char *temp = strdup(addr);
    if (!temp) return -1;

    const char delim[] = "/";
    char *saveptr;
    int count = 0;

    // 2. 第一次遍历：计算分割数量
    char *token = strtok_r(temp, delim, &saveptr);
    while (token != NULL) {
        count++;
        token = strtok_r(NULL, delim, &saveptr);
    }

    // 3. 分配字符串数组内存
    *segment = (char **)malloc(count * sizeof(char *));
    if (!*segment) {
        free(temp);
        return -1;
    }

    // 4. 第二次遍历：填充分割结果
    strcpy(temp, addr);  // 重置临时字符串
    token = strtok_r(temp, delim, &saveptr);
    int i = 0;
    while (token != NULL) {
        (*segment)[i] = strdup(token);  // 复制每个子串
        if (!(*segment)[i]) {
            // 内存分配失败时清理
            for (int j = 0; j < i; j++) free((*segment)[j]);
            free(*segment);
            free(temp);
            return -1;
        }
        i++;
        token = strtok_r(NULL, delim, &saveptr);
    }

    // 5. 释放临时内存
    free(temp);
    return count;
}

int recvn(int sockfd, void *buf, ssize_t length){
    char *p = (char *)buf;//char* 是因为偏移以1个字节为单位
    ssize_t cursize = 0;
    while(cursize < length){
        ssize_t sret = recv(sockfd,p+cursize,length-cursize,0);
        cursize += sret;
    }
    return 0;
}

//下载
int getsFunc(int sockfd, char *filename) {
    int file_len=strlen(filename);
    send(sockfd,&file_len,sizeof(int),MSG_NOSIGNAL);
    send(sockfd,filename,file_len,MSG_NOSIGNAL);
    off_t filesize;
    recv(sockfd,&filesize,sizeof(off_t),MSG_WAITALL);
    if(filesize==-1)
    {
        printf("no such file\n");                          
        return 0;
    }
    else
    {
        printf("filesize=%ld\n",filesize);
    }
    int fd=open(filename,O_RDWR|O_CREAT|O_TRUNC,0666);
    char buf[4096]={0};
    int cursize=0;
    while(cursize<filesize)
    {
        int recvsize=filesize-cursize;
        if(recvsize>=4096)
            recvsize=4096;
        int ret=recv(sockfd,buf,recvsize,MSG_WAITALL);
        write(fd,buf,ret);
        cursize+=recvsize;
    }    return 0;
}

//上传文件
int putsFunc(int netfd, char *filename) {
    int file_len;
    recv(netfd,&file_len,sizeof(file_len),MSG_WAITALL);
    recv(netfd,filename,file_len,MSG_WAITALL);
    int access_ret = access(filename, F_OK);
    int fd;
    off_t filesize;
    if (access_ret == -1)
    {
        //发送-1给对面i
        off_t a=(off_t)access_ret;
        send(netfd,&a,sizeof(off_t),MSG_NOSIGNAL);
        printf("no such file\n");
        return 0;
    }
    else
    {
        fd=open(filename,O_RDWR);
        struct stat statbuf;
        fd=open(filename,O_RDWR);
        fstat(fd,&statbuf);
         filesize=statbuf.st_size;
        send(netfd,&filesize,sizeof(off_t),MSG_NOSIGNAL);
    }
    sendfile(netfd,fd,NULL,filesize);
    return 0;
}



